package com.zzm.shortlink.project.service.impl;


import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzm.shortlink.project.dao.entity.LinkAccessStatsDO;
import com.zzm.shortlink.project.dao.entity.ShortLinkDO;
import com.zzm.shortlink.project.dao.mapper.LinkAccessStatsMapper;
import com.zzm.shortlink.project.dao.mapper.ShortLinkMapper;
import com.zzm.shortlink.project.dto.req.*;
import com.zzm.shortlink.project.dto.resp.ShortLinkPageRespDTO;
import com.zzm.shortlink.project.service.RecycleBinService;
import com.zzm.shortlink.project.toolkit.LinkUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.zzm.shortlink.project.common.constant.RedisKeyConstant.GOTO_IS_NULL_SHORT_LINK_KEY;
import static com.zzm.shortlink.project.common.constant.RedisKeyConstant.GOTO_SHORT_LINK_KEY;

/**
 * 回收站管理接口实现层
 */
@Service
@RequiredArgsConstructor
public class RecycleBinServiceImpl extends ServiceImpl<ShortLinkMapper, ShortLinkDO> implements RecycleBinService {

    private final StringRedisTemplate stringRedisTemplate;

    private final LinkAccessStatsMapper linkAccessStatsMapper;

    @Override
    public void saveRecycleBin(RecycleBinSaveReqDTO requestParam) {
        LambdaQueryWrapper<ShortLinkDO> updateWrapper = Wrappers.lambdaQuery(ShortLinkDO.class)
                .eq(ShortLinkDO::getFullShortUrl, requestParam.getFullShortUrl())
                .eq(ShortLinkDO::getGid, requestParam.getGid())
                .eq(ShortLinkDO::getEnableStatus, 0)
                .eq(ShortLinkDO::getDelFlag, 0);

        ShortLinkDO shortLinkDO = ShortLinkDO.builder()
                .enableStatus(1)
                .build();
        baseMapper.update(shortLinkDO, updateWrapper);

        //将创建短链接时设置的缓存删掉
        stringRedisTemplate.delete(String.format(GOTO_SHORT_LINK_KEY, requestParam.getFullShortUrl()));


    }
    /**
     * 分页查询短链接
     *
     * @param requestParam 分页查询短链接请求参数
     * @return 短链接分页返回结果
     */
    @Override
    public IPage<ShortLinkPageRespDTO> pageShortLink(ShortLinkRecycleBinPageReqDTO requestParam) {

        LambdaQueryWrapper<ShortLinkDO> queryWrapper = Wrappers.lambdaQuery(ShortLinkDO.class)
                .in(ShortLinkDO::getGid, requestParam.getGidList())
                .eq(ShortLinkDO::getEnableStatus, 1)
                .eq(ShortLinkDO::getDelFlag, 0)
                .orderByDesc(ShortLinkDO::getUpdateTime);
        IPage<ShortLinkDO> basicResultPage = baseMapper.selectPage(requestParam, queryWrapper);
        IPage<ShortLinkPageRespDTO> resultPage = getShortLinkUvPvUip(basicResultPage);
        return resultPage.convert(each -> {
            ShortLinkPageRespDTO result = BeanUtil.toBean(each, ShortLinkPageRespDTO.class);
            result.setDomain("http://" + result.getDomain());
            return result;
        });

    }

    /**
     * 获取短链接历史和今日访问统计
     * @param page
     * @return
     */

    private IPage<ShortLinkPageRespDTO> getShortLinkUvPvUip(IPage<ShortLinkDO> page) {
        return page.convert(each->{
            LambdaQueryWrapper<LinkAccessStatsDO> queryWrapper = Wrappers.lambdaQuery(LinkAccessStatsDO.class)
                    .eq(LinkAccessStatsDO::getFullShortUrl, each.getFullShortUrl());
            List<LinkAccessStatsDO> linkAccessStatsDOList = linkAccessStatsMapper.selectList(queryWrapper);

            ShortLinkPageRespDTO linkPageRespDTO = BeanUtil.toBean(each, ShortLinkPageRespDTO.class);
            int totalPv = linkAccessStatsDOList.stream().mapToInt(LinkAccessStatsDO::getPv).sum();
            int totalUv = linkAccessStatsDOList.stream().mapToInt(LinkAccessStatsDO::getUv).sum();
            int totalUip = linkAccessStatsDOList.stream().mapToInt(LinkAccessStatsDO::getUip).sum();

            int todayPv = linkAccessStatsDOList.stream()
                    .filter(item -> {
                        LocalDate itemDate  = item.getDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                        LocalDate today = LocalDate.now();
                        return itemDate.isEqual(today);
                    })
                    .mapToInt(LinkAccessStatsDO::getPv)
                    .sum();

            int todayUv = linkAccessStatsDOList.stream()
                    .filter(item -> {
                        LocalDate itemDate  = item.getDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                        LocalDate today = LocalDate.now();
                        return itemDate.isEqual(today);
                    })
                    .mapToInt(LinkAccessStatsDO::getUv)
                    .sum();

            int todayUip = linkAccessStatsDOList.stream()
                    .filter(item -> {
                        LocalDate itemDate  = item.getDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                        LocalDate today = LocalDate.now();
                        return itemDate.isEqual(today);
                    })
                    .mapToInt(LinkAccessStatsDO::getUip)
                    .sum();
            linkPageRespDTO.setTotalPv(totalPv);
            linkPageRespDTO.setTotalUv(totalUv);
            linkPageRespDTO.setTotalUip(totalUip);
            linkPageRespDTO.setTodayPv(todayPv);
            linkPageRespDTO.setTodayUv(todayUv);
            linkPageRespDTO.setTodayUip(todayUip);
            return linkPageRespDTO;
        });

    }
    /**
     * 恢复短链接
     *
     * @param requestParam 请求参数
     */
    @Override
    public void recoverRecycleBin(RecycleBinRecoverReqDTO requestParam) {
        LambdaQueryWrapper<ShortLinkDO> updateWrapper = Wrappers.lambdaQuery(ShortLinkDO.class)
                .eq(ShortLinkDO::getFullShortUrl, requestParam.getFullShortUrl())
                .eq(ShortLinkDO::getGid, requestParam.getGid())
                .eq(ShortLinkDO::getEnableStatus, 1)
                .eq(ShortLinkDO::getDelFlag, 0);

        ShortLinkDO shortLinkDO = ShortLinkDO.builder()
                .enableStatus(0)
                .build();
        baseMapper.update(shortLinkDO, updateWrapper);

        //将创建短链接时设置的缓存删掉
        stringRedisTemplate.delete(String.format(GOTO_IS_NULL_SHORT_LINK_KEY, requestParam.getFullShortUrl()));

    }

    /**
     * 从回收站移除短链接
     *
     * @param requestParam 移除短链接请求参数
     */
    @Override
    public void removeRecycleBin(RecycleBinRemoveReqDTO requestParam) {
        LambdaUpdateWrapper<ShortLinkDO> updateWrapper = Wrappers.lambdaUpdate(ShortLinkDO.class)
                .eq(ShortLinkDO::getFullShortUrl, requestParam.getFullShortUrl())
                .eq(ShortLinkDO::getGid, requestParam.getGid())
                .eq(ShortLinkDO::getEnableStatus, 1)
                .eq(ShortLinkDO::getDelTime, 0L)
                .eq(ShortLinkDO::getDelFlag, 0);
        ShortLinkDO delShortLinkDO = ShortLinkDO.builder()
                .delTime(System.currentTimeMillis())
                .build();
        delShortLinkDO.setDelFlag(1);
        baseMapper.update(delShortLinkDO, updateWrapper);
    }
}